package com.mlh.dp.背包问题.a01背包;

import org.junit.Test;

import java.util.Arrays;

/**
 * @author 缪林辉
 * @date 2024/4/19 10:14
 * @DESCRIPTION
 */
// 有一堆石头，用整数数组 stones 表示。其中 stones[i] 表示第 i 块石头的重量。
// 每一回合，从中选出任意两块石头，然后将它们一起粉碎。假设石头的重量分别为 x 和 y，且 x <= y。那么粉碎的可能结果如下：
// 如果 x == y，那么两块石头都会被完全粉碎；
// 如果 x != y，那么重量为 x 的石头将会完全粉碎，而重量为 y 的石头新重量为 y-x。
// 最后，最多只会剩下一块 石头。返回此石头 最小的可能重量 。如果没有石头剩下，就返回 0。
public class 最后一块石头的重量2 {
    //妈的 就是分割等和子集的变体而已，没想到这一点很难做
    //思路和分割等和子集一模一样
    public int method1(int[] stones) {
        int total =0;
        for (int i = 0; i < stones.length; i++) {
            total +=stones[i];
        }
        int target= total /2;
        int[] dp = new int[target+1];
        for (int i = 0; i < stones.length ; i++) {
            for (int j = target; j >=stones[i] ; j--) {
                dp[j]=Math.max(dp[j],dp[j-stones[i]]+stones[i]);
            }
            if((total -dp[target])-dp[target]==0){//剪枝
                return 0;
            }
        }
        return (total -dp[target])-dp[target];
    }

    public int practice(int[] stones) {
        int total=0;
        for (int i = 0; i < stones.length; i++) {
            total+=stones[i];
        }
        int[] dp=new int[total/2+1];
        for (int i = 0; i < stones.length; i++) {
            for (int j = total/2; j >=stones[i] ; j--) {
                dp[j]=Math.max(dp[j],dp[j-stones[i]]+stones[i]);
            }
            System.out.println(Arrays.toString(dp));
        }
        return total-dp[total/2]-dp[total/2];//总重量减去 两堆相互抵消的重量，剩下的重量就是没有被抵消的重量
    }

    @Test
    public void tset(){
        practice(new int[]{2,7,4,1,8,1});
    }
}
